import java.util.concurrent.locks.ReentrantLock;

// Java Lock 接口例子
public class Lock {
    
    public static void main(String[] args) {
        // synchronized_example();
        lock_example();
    }
    // 守护线程
    public static void daemon(){
        Thread A = new Thread(()->{
            int i = 10;
            while(i-- > 0){
             System.out.println(Thread.currentThread().getName()+"::"+Thread.currentThread().isDaemon());
            }
        },"A_Thread");
        A.setDaemon(false);
        A.start();
        
        System.out.println(Thread.currentThread().getName()+" over");
    }
    
    public static void synchronized_example(){
        // synchronized 例子
        // 3 个售票员卖 30 张票
        // 创建资源类-》定义属性方法
        System.out.println("synchronized");
        Ticket ticket = new Ticket();
        // Runnable 接口
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"S1");
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"S2");
        Thread thread3 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"S3");
        thread1.start();
        thread2.start();
        thread3.start(); 
    }
    // Lock
    public static void lock_example(){
        System.out.println("Lock");
        L_Ticket ticket = new L_Ticket();
        // Runnable 接口
        // lamda 优化
        // start() 里面调用了 native 方法
        // 所以线程调用 start 的时候，是操作系统决定是否启动的 
        new Thread(()->{
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        },"L1").start();

        new Thread(()->{
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        },"L2").start();

        new Thread(()->{
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        },"L3").start();
    }
}


// 资源类 synchronized
class Ticket{
    private int number = 30;
    public synchronized void sale(){
        if(number > 0){
            System.out.println(Thread.currentThread().getName()+" ：卖出票，剩下 "+number --+" 张票");
        }        
    }
}
// 资源类 lock
class L_Ticket{
    private int number = 30;
    // 可重入锁
    private final ReentrantLock lock = new ReentrantLock();
    public void sale(){
        // 上锁
        lock.lock();
        try{
            if(number > 0){
                System.out.println(Thread.currentThread().getName()+" ：卖出票，剩下 "+number --+" 张票");
            }   
        }     
        // 解锁
        finally{// 保证无论如何都解锁，防止异常无法解锁
            lock.unlock();
        }
    }
}